package com.leyou.auth.service;

import com.leyou.auth.config.JwtProperties;
import com.leyou.common.auth.entity.Payload;
import com.leyou.common.auth.entity.UserInfo;
import com.leyou.common.auth.utils.JwtUtils;
import com.leyou.common.auth.utils.RsaUtils;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.CookieUtils;
import com.leyou.user.client.UserClient;
import com.leyou.user.dto.UserDTO;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class AuthService {

    @Autowired
    private UserClient userClient;

    @Autowired
    private JwtProperties jwtProperties;

    public void login(String username, String password, HttpServletResponse response) {
//         1、根据用户名和密码从用户中心中查询用户信息
        try {
            UserDTO userDTO = userClient.queryByUsernameAndPassword(username, password);
            if(userDTO==null){
                throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
            }
//         2、jwt加密
            UserInfo userInfo = new UserInfo(userDTO.getId(),userDTO.getUsername(),"guest");
//            PrivateKey privateKey = RsaUtils.getPrivateKey(jwtProperties.getPriKeyPath());
            putTokenToCookie(response, userInfo);
        } catch (Exception e) {
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }

    }

    private void putTokenToCookie(HttpServletResponse response, UserInfo userInfo) {
        String token = JwtUtils.generateTokenExpireInMinutes(userInfo, jwtProperties.getPrivateKey(), 30);
//         3、加密后的token放到cookie中
        CookieUtils.newCookieBuilder()
                .name(jwtProperties.getUser().getCookieName()) //cookie名称
                .value(token)   //cookie的值
                .httpOnly(true) //防止XSS攻击  ：可以使用js脚本篡改cookie信息
                .domain(jwtProperties.getUser().getCookieDomain())
                .response(response)
                .maxAge(60 * 60 * 24)  //cookie的存活时间
                .build();
    }

    //    从token中获取用户信息UserInfo
    public UserInfo verifyUser(HttpServletRequest request,HttpServletResponse response) {
        try {
//        1、token怎么获取？ 从cookie中获取
            String token_cookie = CookieUtils.getCookieValue(request, jwtProperties.getUser().getCookieName());
//         2、如何解析token
//            PublicKey publicKey = RsaUtils.getPublicKey(jwtProperties.getPubKeyPath());
            Payload<UserInfo> payload = JwtUtils.getInfoFromToken(token_cookie, jwtProperties.getPublicKey(), UserInfo.class);
//            判断token是否退出
            Boolean aBoolean = redisTemplate.hasKey(payload.getId());
            if(aBoolean){ //如果为true 表示redis中有此数据 意味着这个token退出了
                throw new LyException(ExceptionEnum.UNAUTHORIZED);
            }

            UserInfo userInfo = payload.getUserInfo();
            Date expiration = payload.getExpiration(); //即将失效时间
            Date nowTime = new Date(); //当前时间
//            int i = expiration - nowTime;
//            即将失效时间-当前时间 <= 10 等同于 即将失效时间-10<=当前时间
           /* if(即将失效时间-10<=当前时间){
                重新生成token
            }*/
            DateTime dateTime = new DateTime(expiration).minusMinutes(10);
           if(dateTime.isBeforeNow()){
               putTokenToCookie(response, userInfo);
           }
//          如果发现token即将失效（10分钟），重新生成token
            return userInfo;
        } catch (Exception e) {
            e.printStackTrace();
            throw new LyException(ExceptionEnum.UNAUTHORIZED);
        }
    }

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void logout(HttpServletRequest request, HttpServletResponse response) {
        String token_cookie = CookieUtils.getCookieValue(request, jwtProperties.getUser().getCookieName());

        Payload<UserInfo> payload = JwtUtils.getInfoFromToken(token_cookie, jwtProperties.getPublicKey(), UserInfo.class);
        String payloadId = payload.getId();
//        删除cookie
        CookieUtils.deleteCookie(jwtProperties.getUser().getCookieName(),jwtProperties.getUser().getCookieDomain(),response);

//        把此token放入到redis中表示不能用  保存30分钟
        redisTemplate.boundValueOps(payloadId).set("",30, TimeUnit.MINUTES);


        System.out.println("执行了删除cookie的操作");
    }
}
